function compose(...filters) {
  this.filters = filters;
  this.i = 0;
  async function doFilter(t) {
    if (this.i < this.filters.length) {
      const filter = this.filters[this.i++];
      await filter(t, doFilter);
    }
  }
  return doFilter;
}

const f1 = async (so, doFilter) => {
  so.value += '1';
  await doFilter(so);
  so.value += 'a';
};

const f2 = async (so, doFilter) => {
  so.value += '2';
  await doFilter(so);
  so.value += 'b';
};

const f3 = async (so, doFilter) => {
  so.value += '3';
  await doFilter(so);
  so.value += 'c';
};

(async () => {
  const doFilter = compose(f1, f2, f3);

  const so = { value: 'x' };
  await doFilter(so);

  console.log(so.value === 'x123cba'); // true
})();
